/*
Copyright (C) 2016  Marien Raat

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include <SFML/Graphics.hpp>
#include <SFML/Network.hpp>
#include <Box2D/Box2D.h>

#include "wheel.h"
#include "carExhaust.h"

class Car {
public:
    Car();
    Car(b2World *world);
    void initialize(b2World *world);

    // Save velocity and angular velocity
    void updateFromPacket(sf::Packet &packet);
    void saveToPacket(sf::Packet &packet);

    void setTextures(sf::Texture *carTexture,
                     sf::Texture *exhaustTexture);

    void setInWorld(bool inWorld);
    bool getInWorld() { return inWorld; }

    b2Body *getBody() { return body; }

    // Only works if inWorld
    void setPosition(sf::Vector2f position);
    sf::Vector2f getPosition();

    // Only works if inWorld
    void setRotation(float rotationInDegrees);
    float getRotation();

    void update();
    void draw(sf::RenderTarget *target);

    // Current movement
    float power, // between -1.0 and 1.0 where positive is forward
        turning; // between -1.0 and 1.0 where positive is right
    bool boosting, drifting;

    int dashDirection; // -1 is not dashing

    float boostLeft;
private:
    b2BodyDef bodyDef;
    b2PolygonShape bodyShape;
    b2FixtureDef fixtureDef;
    b2Body *body;
    b2World *world;

    Wheel frontLeftWheel, frontRightWheel,
        backLeftWheel, backRightWheel;

    sf::Texture *carTexture;
    sf::Sprite carSprite;
    CarExhaust carExhaust;
    float boostUsed;

    float dashingTimeLeft; // The time the car remains uncontrollable
    float nextDashTimeLeft; // Time until the next dash is possible

    // Whether the car is currently in the world
    bool inWorld;

    void applyMovement();

    void dash();

    // Initialize the body
    void createBodyDefinitions();
};

sf::Packet &operator <<(sf::Packet &packet, Car &car);
sf::Packet &operator >>(sf::Packet &packet, Car &car);
